#include <iostream>
#include <stdio.h>

#define _BOARD_X_ 9
#define _BOARD_Y_ 13

#define _PLACE_Y_EXCEEDED_ 1
#define _PLACE_X_EXCEEDED_ 2
#define _PLACE_Y_NEGATIVE_ 3
#define _PLACE_X_NEGATIVE_ 4
#define _PLACE_CATCH_ 5
#define _PLACE_OK_ 0


using namespace std;

typedef struct tPosition
{
	int x, y;
};

class clBoard
{
	public:
		int pos[_BOARD_X_][_BOARD_Y_];

		clBoard();
		int place( int id, int x, int y,  tPosition *origin );
		void show();
		int around( tPosition *origin, int vField, int lookX, int lookY, int *onX, int *onY );
		
};

clBoard::clBoard()
{
	int x, y;

	for( y=0; y < _BOARD_Y_; y++ )
	{
		for( x=0; x < _BOARD_X_; x++ )
		{
			pos[x][y] = 0;
		}
	}
}

void clBoard::show()
{
	int x, y;

	for( y=0; y < _BOARD_Y_; y++ )
	{
		for( x=0; x < _BOARD_X_; x++ )
		{
			if( pos[x][y] != 0 )
			{
				cout << "[0;32;31m" << pos[x][y] << "[0;32;0m ";
			}
			else
			{
				cout << pos[x][y] << " ";
			}
		}
		
		cout << "\r\n";
	}
}

int clBoard::place( int id, int x, int y, tPosition *origin )
{
	int status, gotoX, gotoY;
	
	//gotoX = origin->x + x;
	//gotoY = origin->y + y;
	
	gotoX = x;
	gotoY = y;
	
	if( gotoX < 0 )
	{
		status = _PLACE_X_NEGATIVE_;
	}
	else if( gotoY < 0 )
	{
		status = _PLACE_Y_NEGATIVE_;
	}
	else if( gotoX >= _BOARD_X_ )
	{
		status = _PLACE_X_EXCEEDED_;
	}
	else if( gotoY >= _BOARD_Y_ )
	{
		status = _PLACE_Y_EXCEEDED_;
	}
	else
	{
		// reseta a posicao original
		if( pos[origin->x][origin->y] == id )
		{
			pos[origin->x][origin->y] = 0;
		}
		
		// achou algo
		if( pos[ gotoX ][ gotoY ] != id && pos[ gotoX ][ gotoY ] != 0 )
		{
			status = _PLACE_CATCH_;
			pos[ gotoX ][ gotoY ] = 9;
		}
		else
		{
			// seta a posicao atual
			pos[ gotoX ][ gotoY ] = id;
			
			// retornar ok
			status = _PLACE_OK_;	
		}
	}
		
	return status;
}

// position for the current position
// vfield for the vision field of the character
// lookX for WHERE he's looking on x (+1 or -1)
// lookY for WHERE he's looking on Y (+1 or -1)
// onX for where something were found on X
// onY same for Y
// returns 0 if none found, !0 if something were found.
int clBoard::around( tPosition *origin, int vField, int lookX, int lookY, int *onX, int *onY )
{
	int x, y, status = 0;
	int endX, endY;
	
	endX = origin->x + (lookX * vField);
	endY = origin->y + (lookY * vField);
	
	if( endX < 0 )
	{
		endX = 0;
	}
	else if( endX > _BOARD_X_ )
	{
		endX = _BOARD_X_ - 1;
	}
	
	if( endY < 0 )
	{
		endY = 0;
	}
	else if( endY > _BOARD_Y_ )
	{
		endY = _BOARD_Y_ - 1;
	}
	
	for( x = origin->x; x != endX && !status; x += lookX )
	{
		for( y = origin->y; y != endY && !status; y+= lookY )
		{
			cout << "Quem esta em " << origin->x << "," << origin->y;
			cout << " campo de visao maximo (" << vField << ") para " << endX << "," << endY;
			cout << " olhando em " << x << "," << y << "\r\n";
			if( x != origin->x && y != origin->y && pos[x][y] != 0 )
			{
				*onX = x;
				*onY = y;
				cout << "ALGO EM " << x << "," << y << "!!\r\n";
				status = pos[x][y];
			}
			else 
			{
				*onX = -1;
				*onY = -1;
				cout << "NADA\r\n";
			}
		}
	}
	
	return status;
}

class clHunter
{
	//private:
	public:
		int id;
		
		int stepX;
		int stepY;
		
		clBoard *board;
		tPosition pos;
		tPosition seen;
		
		int vField;
	//public:
		clHunter( clBoard *boardPtr, int x, int y );
		
		int moveto( void );
		int moveto( int x, int y );
		int follow( void );
		
		int look( void );
};

clHunter::clHunter( clBoard *boardPtr, int x, int y )
{
	board = boardPtr;
	
	id     = 1;
	stepX  = 1;
	stepY  = 1;
	
	vField = 3;
	
	moveto( x, y );
}

int clHunter::moveto( void )
{
	int x, y;
	
	x = pos.x + stepX;
	y = pos.y + stepY;
	
	moveto( x, y );
}

int clHunter::moveto( int x, int y )
{
	int status;
	
	while( (status = board->place(id, x, y, &pos)) )
	{
		//cout << id << ") Teste para " << x << "," << y << "\r\n";
		switch( status )
		{
			case _PLACE_Y_NEGATIVE_:
				if( x == 0 ) x++;
				y=0;
				stepY = -stepY;
				break;
				
			case _PLACE_X_NEGATIVE_:
				if( y == 0 ) y++;
				x=0;
				stepX = -stepX;
				break;
			
			case _PLACE_Y_EXCEEDED_:
				if( x == 0 ) x++;
				y=_BOARD_Y_-1;
				stepY = -stepY;
				break;
				
			case _PLACE_X_EXCEEDED_:
				if( y == 0 ) y++;
				x=_BOARD_X_-1;
				stepX = -stepX;
				break;
				
			case _PLACE_CATCH_:
				cout << "[0;32;40mCATOU!!!![0;32;0m";
				return _PLACE_CATCH_;
				break;
		}
			
	}
	
	pos.x = x;
	pos.y = y;
	
	return 1;
}

int clHunter::look()
{
	int x, y, status;
	
	status = board->around( &pos, vField, (stepX/abs(stepX)), (stepY/abs(stepY)), &x, &y);
	
	seen.x = x;
	seen.y = y;
	
	return status;
}

int clHunter::follow()
{
	int x, y, gotoX, gotoY;
	
	if( seen.x < 0 || seen.y < 0 )
	{
		return moveto();
	}
	else
	{
		cout << "[0;32;40mVIU EM " << seen.x << "," << seen.y << "!!!![0;32;0m";
	}
	
	x = seen.x;
	y = seen.y;
	
	if( pos.x + abs(stepX) >= x )
	{
		gotoX = x;
	}
	else
	{
		// se ele estaria correndo pro outro lado, trocamos
		if( x > (stepX+pos.x/abs(stepX+pos.x)) )
		{
			stepX*=(-1);
			gotoX= pos.x + stepX;
		}
	}
	
	if( pos.y + abs(stepY) >= y )
	{
		gotoY = y;	
	}
	
	return moveto( gotoX, gotoY );
}

int main()
{
	clHunter *hunter, *prey;
	clBoard *board;
	
	
	int step = 0, step2 = 0;
	
	board = new clBoard();

	hunter = new clHunter( board, 0, 4);
	prey   = new clHunter( board, 7, 0);
	prey->id = 2;
	prey->stepX=2;
	prey->stepY=2;
		
	
	do
	{
		board->show();
		hunter->moveto();
		if( hunter->look() )
		{
			step = hunter->follow();
		}
		step2 = prey->moveto();
		//scanf("%d", &step);
		//cout << "============================================\r\n";
		sleep(1);
		system("clear");
	}
	while( step != _PLACE_CATCH_ && step2 != _PLACE_CATCH_);
	return 0;
}
